﻿//-----------------------------------------------------------------------
// <Copyright>
// * Copyright (C) 2022 RuYiAdmin All Rights Reserved
// </Copyright>
//-----------------------------------------------------------------------

using RuYiAdmin.Net.CommonInfrastructure.Configurations;
using RuYiAdmin.Net.CommonInfrastructure.Models;
using RuYiAdmin.Net.EntityDataModel.DataTransformationModel.SystemModel;
using RuYiAdmin.Net.EntityDataModel.EntityModel.SystemModel;
using RuYiAdmin.Net.RepositoryLayer.DataRepository.Interface.FrameworkInterface;
using RuYiAdmin.Net.RepositoryLayer.DataRepository.Interface.SystemInterface;
using RuYiAdmin.Net.ServiceLayer.BaseService.Implementation;
using RuYiAdmin.Net.ServiceLayer.BusinessService.Interface.SystemInterface;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace RuYiAdmin.Net.ServiceLayer.BusinessService.Implementation.SystemImplementation
{
    /// <summary>
    /// 数据字典业务层实现
    /// </summary>
    class SysCodeTableService : RuYiAdminBaseService<SysCodeTable>, ISysCodeTableService
    {
        #region 属性及构造函数

        /// <summary>
        /// 数据字典仓储实例
        /// </summary>
        private readonly ISysCodeTableRepository CodeTableRepository;

        /// <summary>
        /// Redis仓储实例
        /// </summary>
        private readonly IRedisRepository RedisRepository;

        /// <summary>
        /// 业务日志仓储接口实例
        /// </summary>
        private readonly ILoggerRepository LoggerRepository;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="CodeTableRepository"></param>
        /// <param name="RedisRepository"></param>
        /// <param name="LoggerRepository"></param>
        public SysCodeTableService(ISysCodeTableRepository CodeTableRepository,
                                   IRedisRepository RedisRepository,
                                   ILoggerRepository LoggerRepository) : base(CodeTableRepository)
        {
            this.CodeTableRepository = CodeTableRepository;
            this.RedisRepository = RedisRepository;
            this.LoggerRepository = LoggerRepository;
        }

        #endregion

        #region 服务层公有方法

        #region 获取字典树

        /// <summary>
        /// 获取字典树
        /// </summary>
        /// <returns>ActionResponseResult</returns>
        public async Task<QueryResponseResult<SysCodeTableDTO>> GetCodeTreeNodes()
        {
            var result = new List<SysCodeTableDTO>();

            var codes = await this.RedisRepository.GetAsync<List<SysCodeTableDTO>>(RuYiGlobalConfig.SystemCacheConfig.CodeTableCacheName);
            var parentCodes = codes.Where(t => t.ParentId == null).OrderBy(t => t.SerialNumber).ToList();
            foreach (var item in parentCodes)
            {
                GetNodeChildren(item, codes);
            }
            result.AddRange(parentCodes);

            var queryResponseResult = QueryResponseResult<SysCodeTableDTO>.OK(result);
            return queryResponseResult;
        }

        #endregion

        #region 加载数据字典缓存

        /// <summary>
        /// 加载数据字典缓存
        /// </summary>
        public async Task LoadSystemCodeTableCache()
        {
            int totalCount = 0;
            var codes = (await this.CodeTableRepository.DefaultSqlQueryAsync<SysCodeTableDTO>(new SearchCondition(), totalCount)).ToList();
            await this.RedisRepository.SetAsync(RuYiGlobalConfig.SystemCacheConfig.CodeTableCacheName, codes, -1);

            this.LoggerRepository.Info("系统数据字典缓存加载完成");
        }

        #endregion

        #region 清理数据字典缓存

        /// <summary>
        /// 清理数据字典缓存
        /// </summary>
        public async Task ClearSystemCodeTableCache()
        {
            await this.RedisRepository.DeleteAsync(new string[] { RuYiGlobalConfig.SystemCacheConfig.CodeTableCacheName });

            this.LoggerRepository.Info("系统数据字典缓存清理完成");
        }

        #endregion

        #endregion

        #region 服务层私有方法

        /// <summary>
        /// 递归树
        /// </summary>
        /// <param name="root">根节点</param>
        /// <param name="codes">字典列表</param>
        private void GetNodeChildren(SysCodeTableDTO root, List<SysCodeTableDTO> codes)
        {
            var list = codes.Where(t => t.ParentId == root.Id).ToList();
            if (list.Count > 0)
            {
                root.Children = new List<SysCodeTableDTO>();
                root.Children.AddRange(list.OrderBy(t => t.SerialNumber).ToList());
                foreach (var item in list)
                {
                    GetNodeChildren(item, codes);
                }
            }
        }

        #endregion
    }
}
